package org.streets.eis.setting.validatior;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.validation.AbstractFormValidator;
import org.apache.wicket.model.IModel;

import org.streets.eis.component.grid.TableList;

/**
 * 多字段验证for TableList
 * 
 */
public abstract class TableListValidator<T extends Serializable> extends AbstractFormValidator{
	private static final long serialVersionUID = 1L;

	private TableList<T> tableList;
	
	private String resourceKey;
	
	private String[] fields ;
	
	private Map<T,FormComponent<?>[]> editedRows = new HashMap<T,FormComponent<?>[]>();
	
	/** 
	 * @param resourceKey	资源的key 
	 * @param tableList 要验证的tableList
	 * 
	 */
	public TableListValidator(String resourceKey,String... fields){
		this.fields = fields;
		this.resourceKey = resourceKey;
	}

	public FormComponent<?>[] getDependentFormComponents(){
		return null;
	}

	@SuppressWarnings("unchecked")
	public void validate(Form<?> form){
		WebMarkupContainer rows = (WebMarkupContainer)tableList.get("form:bodyContainer:body:row");
		if (rows != null) {
			for (Iterator<?> i = rows.iterator(); i.hasNext();) {
				WebMarkupContainer component = (WebMarkupContainer) i.next();
				IModel<T> rowModel = (IModel<T>)component.getDefaultModel();
				if (tableList.isItemEdited(rowModel)){
					validateRow(component,rowModel.getObject());
				}
			}
		}
		if (editedRows.size()>0 && !doValidate(editedRows)){
			for (FormComponent<?>[] dependentComponents : editedRows.values()){
				if (dependentComponents[0].isValid()) { 
					error(dependentComponents[0],newVariablesMap(dependentComponents));
				}
			}
		}
	}
	
	public TableList<T> getTableList() {
		return tableList;
	}
	
	public TableListValidator<T> setTableList(TableList<T> tableList){
		this.tableList = tableList;
		return this;
	}
	
	protected void validateRow(WebMarkupContainer row,T object){
		FormComponent<?>[] dependentComponents = new FormComponent<?>[fields.length];
		for (int i=0; i <fields.length; i++){
			FormComponent<?> formComponent = (FormComponent<?>) row.get("item:"+fields[i]+":editableField");
			if(!formComponent.isValid()){
				return;
			}
			dependentComponents[i] = formComponent;
		}
		
		if (dependentComponents.length>0){
			editedRows.put(object, dependentComponents);
			if (!doValidate(dependentComponents,object)){
				error(dependentComponents[0],newVariablesMap(dependentComponents));
			}
		}
	}
	
	@Override
	protected String resourceKey(){
		return resourceKey;
	}

	protected Map<String, Object> newVariablesMap(FormComponent<?>[] formComponents){
		if (formComponents != null && formComponents.length > 0){
			Map<String, Object> args = new HashMap<String, Object>(formComponents.length * 3);
			for (int i = 0; i < formComponents.length; i++){
				final FormComponent<?> formComponent = formComponents[i];

				String arg = "label" + i;
				IModel<?> label = formComponent.getLabel();
				if (label != null){
					args.put(arg, label.getObject());
				} else {
					args.put(arg, formComponent.getLocalizer().getString(formComponent.getId(),
						formComponent.getParent(), formComponent.getId()));
				}

				args.put("input" + i, formComponent.getInput());
				args.put("name" + i, formComponent.getId());
			}
			return args;
		} else {
			return new HashMap<String, Object>(2);
		}
	}
	
	/**
	 * 单行验证
	 * @param formComponents
	 * @param object
	 * @return
	 */
	public abstract boolean doValidate(FormComponent<?>[] formComponents,T object);
	
	/**
	 * 多行验证
	 * @param editedRows
	 * @return
	 */
	public abstract boolean doValidate(final Map<T,FormComponent<?>[]> editedRows);
	
}
